package zsc.ruanc.practicaltraining.service.Impl;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;
import zsc.ruanc.practicaltraining.exception.ApiException;
import zsc.ruanc.practicaltraining.mapper.*;
import zsc.ruanc.practicaltraining.model.domain.TArticle;
import zsc.ruanc.practicaltraining.model.domain.TStatistic;
import zsc.ruanc.practicaltraining.model.domain.TUser;
import zsc.ruanc.practicaltraining.model.vo.*;
import zsc.ruanc.practicaltraining.service.ArticleService;
import zsc.ruanc.practicaltraining.utils.UploadUtils;

import java.util.*;

@Service
public class ArticleServiceImpl implements ArticleService {

    @Autowired
    private ArticleMapper articleMapper;

    @Autowired
    private StatisticMapper statisticMapper;

    @Autowired
    private CommentMapper commentMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private ClassificationMapper classificationMapper;

    @Value("${cbs.imagesPath.file}")
    private String resPath;

    /**
     * 新建文章
     * @param vo
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public boolean insert(ArticleVo vo, int userId) {



        // 新建文章
        TArticle article = new TArticle(vo);
        article.setUserId(userId);
        articleMapper.insert(article);

        classificationMapper.numAndOne(vo.getCategories()); // 分类数量加一

        // 新建文章统计表
        statisticMapper.insert(article.getId());
        return true;
    }

    /**
     * 删除文章
     * @param id
     * @param userId
     * @return
     */
    @Override
    @Transactional
    public boolean delete(int id, Integer userId) {
        int x = articleMapper.delete(id, userId);
        if (x == 0) {
            throw new ApiException(-1, "你没有权限删除");
        }
        return true;
    }

    /**
     * 获得一篇详细的文章
     * @param id 文章id
     * @param userId 用户id
     * @return
     */
    @Override
    public getArticleVo getArticle(int id, Integer userId) {

        getArticleVo vo = new getArticleVo();

        TArticle article = articleMapper.getArticle(id);

        if (article == null) {
            throw new ApiException(404, "文章未找到");
        }

        if (article.getFlag() == false) { //文章未通过，则只允许作者本人查看


            if (userId == -1) { // 管理员

            }
            // null表示游客 || 持有token但是查询的不是自己的文章
            else if (userId == null || userId != article.getUserId()) {
                throw new ApiException(-13, "此文章还未审核");
            }

        }

        statisticMapper.hitsAndOne(id); // 文章访问量加一



        vo.setArticle(article); // 文章
        vo.setAuthor(userMapper.selectNameByUserId(vo.getArticle().getUserId())); // 作者名
        vo.setStatistic(statisticMapper.select(id)); // 统计表

        return vo;

    }

    /**
     * 查询用户的所有文章
     * @param userId
     * @param cur
     * @param size
     * @param flag
     * @return
     */
    @Override
    public Map selectPageByUser(int userId, int cur, int size, Boolean flag) {
        PageHelper.startPage(cur, size).setOrderBy("aId desc");
        PageInfo<getArticleVo> userPageInfo = new PageInfo<>(this.articleMapper.getArticleByUserId(userId, flag));
        Map<String, Object> map = new HashMap();
        map.put("total", userPageInfo.getTotal());
        map.put("list", userPageInfo.getList());
        return map;
    }

    /**
     * 模糊查找
     * @param text
     * @param cur
     * @param size
     * @return
     */
    @Override
    public Map selectPage(String text, int cur, int size) {
        PageHelper.startPage(cur, size).setOrderBy("aId desc");
        PageInfo<getArticleVo> articlePageInfo = new PageInfo<>(this.articleMapper.selectPage(text));
        Map<String, Object> map = new HashMap();
        map.put("list", articlePageInfo.getList());
        map.put("total", articlePageInfo.getTotal());
        return map;
    }

    /**
     * 更新文章
     * @param vo
     * @return
     */
    @Override
    @Transactional
    public boolean updateArticle(UpdateArticleVo vo, int userId) {

        if (!classificationMapper.checkName(vo.getOldCategories())) {
            throw new ApiException(-1, "你是爬虫");
        }

        // 如果用户修改了分类 需要检测参数
        if (!vo.getCategories().equals(vo.getOldCategories())) {

            if (vo.getCategories() != null) {
                // 如果用户传了分类 需要检测是否合法
                // 如果没有传值 就是默认分类
                if (!classificationMapper.checkName(vo.getCategories())) {
                    throw new ApiException(-1, "不要乱填分类");
                }
            } else {
                // 方便后面操作
                vo.setCategories("默认分类");
            }

        }



        vo.setDate(new Date()); // 修改时间
        vo.setUserId(userId);
        int x = articleMapper.updateArticle(vo);
        if (x == 0) {
            throw new ApiException(-13, "你没有权限修改");
        }

        classificationMapper.numCutOne(vo.getOldCategories()); // 旧分类减一
        classificationMapper.numAndOne(vo.getCategories()); // 新分类加一

        return true;
    }

    /**
     * 修改是否可评论
     * @param id
     * @param flag
     * @param userId
     * @return
     */
    @Override
    public boolean updateAllow(int id, boolean flag, int userId) {
        int x = articleMapper.updateAllow(id, flag, userId);
        if (x == 0) {
            throw new ApiException(-13, "你没有权限修改");
        }
        return true;
    }

    /**
     * 上传图片
     * @param file
     * @param id 用户id
     * @return 文件url
     */
    public String uploadImg(MultipartFile file, int id) {
        String path = resPath + String.valueOf(id) + "/"; // 拼接保存路径
        String filename = UploadUtils.saveImg(file, path); // 返回文件名
        return "/res/" + String.valueOf(id) + "/" +filename; // 对外暴露的url
    }

    /**
     * 文章点赞
     * @param articleId
     * @return
     */
    @Override
    public boolean  likesAndOne(int articleId) {
        Boolean flag = articleMapper.getArticleFlag(articleId);
        if (flag == null) {
            throw new ApiException(-404, "没有此文章");
        } else if (flag == false) {
            throw new ApiException(-13, "文章未审核");
        }
        statisticMapper.likesAndOne(articleId); // 加一

        return true;
    }

    /**
     * 取消赞
     * @param articleId
     * @return
     */
    @Override
    public boolean likesCutOne(int articleId) {
        Boolean flag = articleMapper.getArticleFlag(articleId);
        if (flag == null) {
            throw new ApiException(404, "没有此文章");
        } else if (flag == false) {
            throw new ApiException(-13, "文章未审核");
        }

        int x = statisticMapper.likesCutOne(articleId); // 赞减一
        if (x == 0) {
            throw new ApiException(-13, "文章已经一个赞都莫得了，手下留情吧");
        }
        return true;
    }

    /**
     * 上传附件
     * @param file
     * @param id 用户id
     * @return 文件url
     */
    @Override
    public String uploadFile(MultipartFile file, int id) {
        String path = resPath + String.valueOf(id) + "/"; // 拼接保存路径
        String filename = UploadUtils.save(file, path); // 返回文件名
        return "/res/" + String.valueOf(id) + "/" + filename; // 对外暴露的url
    }


    /**
     *   推荐文章
     * @param row
     * @param orderColumnName
     * @return
     */
    @Override
    @Cacheable(value = "recommendList", key = "#orderColumnName + #row")
    public List<getArticleVo> recommendList(int row, String orderColumnName) {
        List<TStatistic> tStatistics = statisticMapper.TopList(orderColumnName, row);
        List<getArticleVo> list = new ArrayList<>();

        for (TStatistic vo : tStatistics) {
            getArticleVo o = new getArticleVo();


            TArticle article = articleMapper.getArticle(vo.getArticleId()); // 文章
            article.setContent(null); // 文章内容不返回
            String s = userMapper.selectNameByUserId(article.getUserId());// 作者名

            o.setStatistic(vo); // 统计表
            o.setAuthor(s);
            o.setArticle(article);

            list.add(o);
        }
        return list;

    }

    // 对用户文章的分析
    @Override
    public Map articleAnalysis(int userId) {
        Map map = new HashMap();
        int noPass = articleMapper.getCount(userId, false);
        int pass = articleMapper.getCount(userId, true);

        String[] classList = articleMapper.classificationList(userId);
        Map<String, Integer> temp = new HashMap<>();
        for (String item : classList) {
            // key在map里面
            if (temp.containsKey(item)) {
                temp.put(item, temp.get(item) + 1);
            } else {
                temp.put(item, 1);
            }
        }

        map.put("total", noPass + pass);
        map.put("noPass", noPass);
        map.put("pass", pass);
        map.put("class", temp);

        return map;

    }


    // 按分类查找
    @Override
    public Map selectByCategories(int cur, int size, String categories) {

        Map<String, Object> map = new HashMap<>();




        PageHelper.startPage(cur, size).setOrderBy("aId desc");
        PageInfo<getArticleVo> articlePageInfo = new PageInfo<>(this.articleMapper.selectByCategories(categories));


        map.put("total", articlePageInfo.getTotal());
        map.put("list", articlePageInfo.getList());


        return map;

    }

    //---------管理员权限---------------------------

    /**
     * 是否通过审核
     * @param id
     * @param flag
     * @return
     */
    @Override
    public boolean updateFlag(int id, boolean flag) {
        int x = articleMapper.updateFlag(id, flag);
        if (x == 0) {
            throw new ApiException(404, "没有找到文章");
        }

        if (flag == true) {

        }

        return true;
    }

    /**
     * 查询所有文章
     * @param cur
     * @param size
     * @param flag 为null时，查询所有文章 为true时，查询所有已审核文章 为false时，查询所有未审核文章
     * @return
     */
    @Override
    public Map selectAll(int cur, int size, Boolean flag) {

        Map<String, Object> map = new HashMap<>();



        PageHelper.startPage(cur, size).setOrderBy("aId desc");
        PageInfo<getArticleVo> articlePageInfo = new PageInfo<>(this.articleMapper.selectAll(flag));


        map.put("total", articlePageInfo.getTotal());
        map.put("list", articlePageInfo.getList());


        return map;

    }

    @Override
    public Map selectByTime(TimeVo vo) {

        Map<String, Object> map = new HashMap<>();



        PageHelper.startPage(vo.getCur(), vo.getSize()).setOrderBy("aId desc");
        PageInfo<getArticleVo> articlePageInfo = new PageInfo<>(this.articleMapper.selectByTime(vo));


        map.put("total", articlePageInfo.getTotal());
        map.put("list", articlePageInfo.getList());


        return map;

    }

    /**
     * 查询本系统的文章数量
     * @param flag 为null时，查询所有文章 为true时，查询所有已审核文章 为false时，查询所有未审核文章
     * @return
     */
    @Override
    public int articleCount(Boolean flag) {
        return articleMapper.getCount(null, flag);
    }


    /**
     * 修改文章统计表值
     * @param vo
     * @return
     */
    @Override
    public boolean updateStatistic(TStatistic vo) {
        if (vo.getCommentsNum() == null && vo.getHits() == null && vo.getLikes() == null) {
            throw new ApiException(400, "你没睡醒吧, 数据都是null");
        }
        statisticMapper.updateCount(vo);
        return true;
    }



}
